/* alert tcp $EXTERNAL_NET $HTTP_PORTS -> $HOME_NET any (msg:"WEB-CLIENT Microsoft DirectShow memory corruption attempt"; flow:to_client,established; content:"RIFF"; content:"AVI "; distance:4; within:4; content:"strf"; metadata:policy security-ips drop, policy balanced-ips drop, service http; classtype:attempted-user; reference:cve,2010-0250; reference:url,technet.microsoft.com/en-us/security/bulletin/MS10-013; sid:16415;)
*/
/*
 * Use at your own risk.
 *
 * Copyright (C) 2005-2008 Sourcefire, Inc.
 * 
 * This file is autogenerated via rules2c, by Brian Caswell <bmc@sourcefire.com>
 */


#include "sf_snort_plugin_api.h"
#include "sf_snort_packet.h"

//#define DEBUG
#ifdef DEBUG
#define DEBUG_SO(code) code
#else
#define DEBUG_SO(code)
#endif

/* declare detection functions */
int rule16415eval(void *p);

/* declare rule data structures */
/* flow:established, to_client; */
static FlowFlags rule16415flow0 = 
{
    FLOW_ESTABLISHED|FLOW_TO_CLIENT
};

static RuleOption rule16415option0 =
{
    OPTION_TYPE_FLOWFLAGS,
    {
        &rule16415flow0
    }
};
#ifndef CONTENT_FAST_PATTERN
#define CONTENT_FAST_PATTERN 0
#endif

static CursorInfo rule16415file_data1 =
{
    0, /* offset */
    CONTENT_BUF_NORMALIZED /* flags */
};

static RuleOption rule16415option1 =
{
#ifndef MISSINGFILEDATA
    OPTION_TYPE_FILE_DATA,
#else
    OPTION_TYPE_SET_CURSOR,
#endif
    {
        &rule16415file_data1
    }
};

// content:"RIFF", depth 0, fast_pattern; 
static ContentInfo rule16415content2 = 
{
    (uint8_t *) "RIFF", /* pattern (now in snort content format) */
    0, /* depth */
    0, /* offset */
    CONTENT_FAST_PATTERN|CONTENT_BUF_NORMALIZED, /* flags */
    NULL, /* holder for boyer/moore PTR */
    NULL, /* more holder info - byteform */
    0, /* byteform length */
    0 /* increment length*/
};

static RuleOption rule16415option2 = 
{
    OPTION_TYPE_CONTENT,
    {
        &rule16415content2
    }
};
// content:"AVI", offset 4, depth 4, relative; 
static ContentInfo rule16415content3 = 
{
    (uint8_t *) "AVI ", /* pattern (now in snort content format) */
    4, /* depth */
    4, /* offset */
    CONTENT_RELATIVE|CONTENT_BUF_NORMALIZED, /* flags */
    NULL, /* holder for boyer/moore PTR */
    NULL, /* more holder info - byteform */
    0, /* byteform length */
    0 /* increment length*/
};

static RuleOption rule16415option3 = 
{
    OPTION_TYPE_CONTENT,
    {
        &rule16415content3
    }
};

// content:"strl", distance 0, relative;
static ContentInfo rule16415content4 =
{
    (uint8_t *) "strl", /* pattern (now in snort content format) */
    0, /* depth */
    0, /* offset */
    CONTENT_RELATIVE|CONTENT_BUF_NORMALIZED, /* flags */
    NULL, /* holder for boyer/moore PTR */
    NULL, /* more holder info - byteform */
    0, /* byteform length */
    0 /* increment length*/
};

static RuleOption rule16415option4 =
{
    OPTION_TYPE_CONTENT,
    {
        &rule16415content4
    }
};

// content:"vids", distance 8, within 4, relative;
static ContentInfo rule16415content5 =
{
    (uint8_t *) "vids", /* pattern (now in snort content format) */
    4, /* depth */
    8, /* offset */
    CONTENT_RELATIVE|CONTENT_BUF_NORMALIZED, /* flags */
    NULL, /* holder for boyer/moore PTR */
    NULL, /* more holder info - byteform */
    0, /* byteform length */
    0 /* increment length*/
};

static RuleOption rule16415option5 =
{
    OPTION_TYPE_CONTENT,
    {
        &rule16415content5
    }
};

// content:"strf", depth 0, relative; 
static ContentInfo rule16415content6 = 
{
    (uint8_t *) "strf", /* pattern (now in snort content format) */
    0, /* depth */
    0, /* offset */
    CONTENT_RELATIVE|CONTENT_BUF_NORMALIZED, /* flags */
    NULL, /* holder for boyer/moore PTR */
    NULL, /* more holder info - byteform */
    0, /* byteform length */
    0 /* increment length*/
};

static RuleOption rule16415option6 = 
{
    OPTION_TYPE_CONTENT,
    {
        &rule16415content6
    }
};

/* references for sid 16415 */
/* reference: cve "2010-0250"; */
static RuleReference rule16415ref1 = 
{
    "cve", /* type */
    "2010-0250" /* value */
};

/* reference: url "technet.microsoft.com/en-us/security/bulletin/MS10-013"; */
static RuleReference rule16415ref2 = 
{
    "url", /* type */
    "technet.microsoft.com/en-us/security/bulletin/MS10-013" /* value */
};

static RuleReference *rule16415refs[] =
{
    &rule16415ref1,
    &rule16415ref2,
    NULL
};
/* metadata for sid 16415 */
/* metadata:service http, policy balanced-ips drop, policy security-ips drop; */
static RuleMetaData rule16415service1 = 
{
    "service http"
};


//static RuleMetaData rule16415policy1 = 
//{
//    "policy balanced-ips drop"
//};
//
//static RuleMetaData rule16415policy2 = 
//{
//    "policy security-ips drop"
//};

static RuleMetaData rule16415policy3 = 
{
    "policy max-detect-ips drop"
};

static RuleMetaData *rule16415metadata[] =
{
    &rule16415service1,
//    &rule16415policy1,
//    &rule16415policy2,
    &rule16415policy3,
    NULL
};

RuleOption *rule16415options[] =
{
    &rule16415option0,
    &rule16415option1,
    &rule16415option2,
    &rule16415option3,
    &rule16415option4,
    &rule16415option5,
    &rule16415option6,
    NULL
};

Rule rule16415 = {
   /* rule header, akin to => tcp any any -> any any */
   {
       IPPROTO_TCP, /* proto */
       "$EXTERNAL_NET", /* SRCIP     */
       "$HTTP_PORTS", /* SRCPORT   */
   
       0, /* DIRECTION */
       "$HOME_NET", /* DSTIP     */
   
       "any", /* DSTPORT   */
   },
   /* metadata */
   { 
       3,  /* genid */
       16415, /* sigid */
       9, /* revision */
       "attempted-user", /* classification */
       0,  /* hardcoded priority XXX NOT PROVIDED BY GRAMMAR YET! */
       "OS-WINDOWS Microsoft DirectShow memory corruption attempt",     /* message */
       rule16415refs /* ptr to references */
       ,rule16415metadata
   },
   rule16415options, /* ptr to rule options */
   &rule16415eval, /* use the built in detection function */
   0 /* am I initialized yet? */
};


/* detection functions */
int rule16415eval(void *p) {
    const uint8_t *cursor_normal = 0;
    SFSnortPacket *sp = (SFSnortPacket *) p;

    const uint8_t *beg_of_payload, *end_of_payload;
    uint16_t biBitCount;
    uint32_t biClrUsed;
   
    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_client;
    if (checkFlow(p, rule16415options[0]->option_u.flowFlags) <= 0 )
        return RULE_NOMATCH;

    //file_data;
    #ifndef MISSINGFILEDATA
    if (fileData(p, rule16415options[1]->option_u.cursor, &cursor_normal) <= 0 )
        return RULE_NOMATCH;
    #else
    if (setCursor(p, rule16415options[1]->option_u.cursor, &cursor_normal) <= 0 )
        return RULE_NOMATCH;
    #endif

    // content:"RIFF", depth 0, fast_pattern;
    if (contentMatch(p, rule16415options[2]->option_u.content, &cursor_normal) <= 0)
        return RULE_NOMATCH;

    // content:"AVI ", offset 4, depth 4, relative;
    if (contentMatch(p, rule16415options[3]->option_u.content, &cursor_normal) <= 0)
        return RULE_NOMATCH;
    // content:"strl", offset 0, relative;
    if (contentMatch(p, rule16415options[4]->option_u.content, &cursor_normal) <= 0)
        return RULE_NOMATCH;
    // content:"vids", offset 8, depth 4, relative
    if (contentMatch(p, rule16415options[5]->option_u.content, &cursor_normal) <= 0)
        return RULE_NOMATCH;
    // content:"strf", depth 0, relative;
    if (contentMatch(p, rule16415options[6]->option_u.content, &cursor_normal) <= 0)
        return RULE_NOMATCH; 

    if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
        return RULE_NOMATCH;
   
    if(cursor_normal + 40 > end_of_payload)
        return RULE_NOMATCH;

    //Jump past strf size DWORD and beginning of bitmapheader
    cursor_normal += 18;

    //extract biBitCount
    biBitCount = *cursor_normal++;
    biBitCount |= *cursor_normal++ << 8;

    //Jump to and extract biClrUsed
    cursor_normal += 16;
    biClrUsed = *cursor_normal++;
    biClrUsed |= *cursor_normal++ << 8;
    biClrUsed |= *cursor_normal++ << 16;
    biClrUsed |= *cursor_normal << 24;

    DEBUG_SO(printf("biBitCount = 0x%02x, biClrUsed = 0x%04x\n", biBitCount, biClrUsed));

    /* Avoid potential wrap and false positive.
     * A shift larger than uint32 will always be greater. */
    if (biBitCount >= 32)
        return RULE_NOMATCH;

    //Alert when...
    if (biClrUsed > (1 << biBitCount))
        return RULE_MATCH;
           
    return RULE_NOMATCH;
}

/*
Rule *rules[] = {
    &rule16415,
    NULL
};
*/

